package client

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"crypto/tls"
	zaplog "k8s_gui_client/log"

	"github.com/tidwall/gjson"
)

type (
	//api client
	K8sApiClient struct {
		Config     gjson.Result
		HttpClient *http.Client
		Server     string
	}
)

const GET_NODES = "/api/v1/nodes"
const GET_PODS = "/api/v1/pods"

var CurrentK8sApiClient *K8sApiClient

// 存储当前使用的配置文件路径
var currentConfigPath string

// 初始化默认配置文件路径
func init() {
	dirname, _ := os.UserHomeDir()
	currentConfigPath = dirname + "/.kube/config"
}

// SetConfigPath 设置新的配置文件路径
func SetConfigPath(configPath string) error {
	// 验证文件是否存在
	_, err := os.Stat(configPath)
	if err != nil {
		errMsg := "配置文件不存在: " + err.Error()
		zaplog.Logger.Error(errMsg)
		fmt.Println(errMsg) // 添加控制台输出以便调试
		return err
	}

	currentConfigPath = configPath
	// 重新初始化客户端
	err = InitK8sApiClient()
	if err != nil {
		errMsg := "重新初始化客户端失败: " + err.Error()
		zaplog.Logger.Error(errMsg)
		fmt.Println(errMsg) // 添加控制台输出以便调试
		return err
	}

	fmt.Println("配置文件设置成功: " + configPath)
	return nil
}

// GetCurrentConfigPath 获取当前配置文件路径
func GetCurrentConfigPath() string {
	return currentConfigPath
}

// .kube/config
func GetHomeConfig() (string, error) {
	f, err := ioutil.ReadFile(currentConfigPath)
	if err != nil {
		zaplog.Logger.Error(err.Error())
		return "", err
	}
	config_str := string(f)

	return config_str, nil
}

func GetClientConfig(config_str string) gjson.Result {
	return gjson.Parse(config_str)
}
func (self *K8sApiClient) GetAPI(url string) (map[string]interface{}, error) {
	req, err := http.NewRequest("GET", self.Server+url, nil)

	if err != nil {
		zaplog.Logger.Error(err.Error())
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")

	res, err := self.HttpClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		zaplog.Logger.Error(err.Error())
	}

	if err == nil {

		//fmt.Println(string(body))
		m := make(map[string]interface{})
		err = json.Unmarshal(body, &m)
		if err == nil {
			return m, nil
		} else {
			return nil, err
		}

	} else {
		return nil, err
	}

}

func (self *K8sApiClient) GetAPIAsYaml(url string) (string, error) {
	req, err := http.NewRequest("GET", self.Server+url, nil)

	if err != nil {
		zaplog.Logger.Error(err.Error())
	}
	req.Header.Add("Content-Type", "application/yaml")
	req.Header.Add("Accept", "application/yaml")

	res, err := self.HttpClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		zaplog.Logger.Error(err.Error())
	}

	if err == nil {

		return (string(body)), nil

	} else {
		return "", err
	}

}

func (self *K8sApiClient) GetAPIAsText(url string) (string, error) {
	req, err := http.NewRequest("GET", self.Server+url, nil)

	if err != nil {
		zaplog.Logger.Error(err.Error())
	}
	res, err := self.HttpClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		zaplog.Logger.Error(err.Error())
	}

	if err == nil {

		return (string(body)), nil

	} else {
		return "", err
	}

}
func (c *K8sApiClient) InitClient() error {
	currentContext_name := c.Config.Get("current-context").String()
	if currentContext_name == "" {
		errMsg := "配置文件中未找到current-context"
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	var currentContext gjson.Result
	var contextFound bool = false

	contexts := c.Config.Get("contexts").Array()
	if len(contexts) == 0 {
		errMsg := "配置文件中未找到contexts配置"
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	for _, c := range contexts {
		if c.Get("name").String() == currentContext_name {
			currentContext = c
			contextFound = true
			break
		}
	}

	if !contextFound {
		errMsg := "在配置文件中未找到名为" + currentContext_name + "的context"
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	user_name := currentContext.Get("context.user").String()
	if user_name == "" {
		errMsg := "context中未找到user配置"
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	cluster_name := currentContext.Get("context.cluster").String()
	if cluster_name == "" {
		errMsg := "context中未找到cluster配置"
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	var user gjson.Result

	users := c.Config.Get("users").Array()

	for _, c := range users {
		if c.Get("name").String() == user_name {
			user = c
		}
	}

	var cluster gjson.Result

	clusters := c.Config.Get("clusters").Array()

	for _, c := range clusters {
		if c.Get("name").String() == cluster_name {
			cluster = c
		}
	}

	certificate := user.Get("user.client-certificate-data").String()

	key := user.Get("user.client-key-data").String()

	server := cluster.Get("cluster.server").String()

	c.Server = server

	fmt.Println("certificate=" + certificate)
	fmt.Println("key=" + key)
	fmt.Println("server=" + server)

	tls_cer, err := base64.URLEncoding.DecodeString(certificate)
	if err != nil {
		return err
	}
	tls_key, err := base64.URLEncoding.DecodeString(key)
	if err != nil {
		return err
	}
	fmt.Println(string(tls_cer))
	fmt.Println(string(tls_key))

	cer, err := tls.X509KeyPair(tls_cer, tls_key)
	if err != nil {
		return err
	}
	tls_config := tls.Config{
		ServerName:         server,
		Certificates:       []tls.Certificate{cer},
		InsecureSkipVerify: true,
	}
	tr := &http.Transport{TLSClientConfig: &tls_config}
	client := &http.Client{
		Transport: tr,
	}

	c.HttpClient = client

	return nil
}

func InitK8sApiClient() error {
	config_str, err := GetHomeConfig()
	if err != nil {
		errMsg := "无法读取配置文件: " + err.Error()
		zaplog.Logger.Error(errMsg)
		fmt.Println(errMsg) // 添加控制台输出以便调试
		return fmt.Errorf("读取配置文件失败: %w", err)
	}

	if config_str == "" {
		errMsg := "配置文件内容为空"
		zaplog.Logger.Error(errMsg)
		fmt.Println(errMsg)
		return fmt.Errorf(errMsg)
	}

	CurrentK8sApiClient = &K8sApiClient{
		Config: GetClientConfig(config_str),
	}

	err = CurrentK8sApiClient.InitClient()
	if err != nil {
		errMsg := "初始化K8s客户端失败: " + err.Error()
		zaplog.Logger.Error(errMsg)
		fmt.Println(errMsg) // 添加控制台输出以便调试
		return fmt.Errorf("初始化K8s客户端失败: %w", err)
	}

	fmt.Println("K8s客户端初始化成功")
	return nil
}
